#include "game.h"

void fshowKeyUp(int i, int j) { printKey(key_up,i,j);}
void fshowKeyDown(int i, int j) { printKey(key_down,i,j);}
void fshowKeyLeft(int i, int j) { printKey(key_left,i,j);}
void fshowKeyRight(int i, int j) { printKey(key_right,i,j);}
void fshowKeyAction(int i, int j) { printKey(key_action,i,j);}
void fshowKeyPause(int i, int j) { printKey(key_pause,i,j);}

int fchangeKeyUp()
{
	int old_key = key_up;
	key_up = getKey();

	if(key_up == key_down)
		key_down = old_key;
	if(key_up == key_left)
		key_left = old_key;
	if(key_up == key_right)
		key_right = old_key;
	if(key_up == key_action)
		key_action = old_key;
	if(key_up == key_pause)
		key_pause = old_key;
	
	return 0;
}
int fchangeKeyDown()
{
	int old_key = key_down;
	key_down = getKey();
	
	if(key_down == key_up)
		key_up = old_key;
	if(key_down == key_left)
		key_left = old_key;
	if(key_down == key_right)
		key_right = old_key;
	if(key_down == key_action)
		key_action = old_key;
	if(key_down == key_pause)
		key_pause = old_key;
	
	return 0;
}
int fchangeKeyLeft()
{ 
	int old_key = key_left;
	key_left = getKey();
	
	if(key_left == key_down)
		key_down = old_key;
	if(key_left == key_up)
		key_up = old_key;
	if(key_left == key_right)
		key_right = old_key;
	if(key_left == key_action)
		key_action = old_key;
	if(key_left == key_pause)
		key_pause = old_key;
	
	return 0;
}

int fchangeKeyRight()
{ 
	int old_key = key_right;
	key_right = getKey();
	
	if(key_right == key_down)
		key_down = old_key;
	if(key_right == key_left)
		key_left = old_key;
	if(key_right == key_up)
		key_up = old_key;
	if(key_right == key_action)
		key_action = old_key;
	if(key_right == key_pause)
		key_pause = old_key;
	
	return 0;
}

int fchangeKeyAction()
{ 
	int old_key = key_action;
	key_action = getKey();
	
	if(key_action == key_down)
		key_down = old_key;
	if(key_action == key_left)
		key_left = old_key;
	if(key_action == key_right)
		key_right = old_key;
	if(key_action == key_up)
		key_up = old_key;
	if(key_action == key_pause)
		key_pause = old_key;
	
	
	return 0;
}
int fchangeKeyPause() 
{
	int old_key = key_pause;
	key_pause = getKey();
	
	if(key_pause == key_down)
		key_down = old_key;
	if(key_pause == key_left)
		key_left = old_key;
	if(key_pause == key_right)
		key_right = old_key;
	if(key_pause == key_action)
		key_action = old_key;
	if(key_pause == key_up)
		key_up = old_key;
	
	return 0;
}

int resolution1() {updateResolution(MODE_640x480); return 1;};
int resolution2() {updateResolution(MODE_800x600); return 1;};
int resolution3() {updateResolution(MODE_1024x768); return 1;};
int resolution4() {updateResolution(MODE_1280x1024); return 1;};

int soundON() {sounds = 1; return 1;}
int soundOFF() {sounds = 0; return 1;}

void fshowResolution(int x, int y)
{
	switch(resolution)
	{
		case MODE_640x480: drawStringAt(STR_640x480, x, y, WHITE, BLACK,1, video, table); break;
		case MODE_800x600: drawStringAt(STR_800x600, x, y, WHITE, BLACK,1, video, table); break;
		case MODE_1024x768: drawStringAt(STR_1024x768, x, y, WHITE, BLACK,1, video, table); break;
		case MODE_1280x1024: drawStringAt(STR_1280x1024, x, y, WHITE, BLACK,1, video, table); break;
	}
}

void fshowSound(int x, int y)
{
	switch(sounds)
	{
		case 0: drawStringAt("OFF", x, y, WHITE, BLACK,1, video, table); break;
		case 1: drawStringAt("ON", x, y, WHITE, BLACK,1, video, table); break;
	}
}

int playMode1() {playGame(GAMEMODE1); return 1;}
int playMode2() {playGame(GAMEMODE2); return 1;}
int playMode3() {playGame(GAMEMODE3); return 1;}

int showScores1() { showScores(GAMEMODE1); return 0;}
int showScores2() { showScores(GAMEMODE2); return 0;}
int showScores3() { showScores(GAMEMODE3); return 0;}

MenuEntry controls_options[] = {{0,".Up",fshowKeyUp,fchangeKeyUp},
								{1,".Down",fshowKeyDown,fchangeKeyDown},
								{2,".Left",fshowKeyLeft,fchangeKeyLeft},
								{3,".Right",fshowKeyRight,fchangeKeyRight},
								{4,".Action",fshowKeyAction,fchangeKeyAction},
								{5,".Pause",fshowKeyPause,fchangeKeyPause},
								{6,".Back",NULL,NULL}};
								
Menu controlsMenu = {NULL,"CONTROLS", controls_options, sizeof (controls_options) / sizeof(controls_options[0]),0};


MenuEntry resolution_options[] = {{0,".640x480",NULL,resolution1},
								  {1,".800x600",NULL,resolution2},
								  {2,".1024x768",NULL,resolution3},
								  {3,".1280x1024",NULL,resolution4},
								  {4,".Back",NULL,NULL}};

Menu resolutionMenu = {NULL,"RESOLUTION", resolution_options, sizeof (resolution_options) / sizeof(resolution_options[0]),0};

MenuEntry sound_options[] = {{0,".ON",NULL,soundON},
							 {1,".OFF",NULL,soundOFF},
							 {2,".Back",NULL,NULL}};

Menu soundMenu = {NULL,"SOUND", sound_options, sizeof (sound_options) / sizeof(sound_options[0]),0};

int fSound() {startMenu(&soundMenu,menu_posH, menu_posV); return 0;}
int fControls() {startMenu(&controlsMenu,menu_posH, menu_posV); return 0;}

int fResolution()
{
	int old_resolution = resolution;
	startMenu(&resolutionMenu,menu_posH, menu_posV);
	
	if(resolution != old_resolution)
	{
		leave_graphics(map);
		video = enter_graphics(resolution, &map);
	}
	
	return 0;
}

MenuEntry options_options[] = {{0, ".Resolution",fshowResolution, fResolution},
							   {1, ".Sound",fshowSound,fSound},
							   {2, ".Controls",NULL,fControls},
							   {3, ".Back",NULL, NULL}};

Menu optionsMenu = {NULL,"OPTIONS", options_options, sizeof (options_options) / sizeof(options_options[0]),0};

MenuEntry play_options[] = {{0, ".1 min", NULL, playMode1},
							{1, ".3 min", NULL, playMode2},
							{2, ".5 min", NULL, playMode3},
							{3, ".Back", NULL, NULL}};
							
Menu playMenu = {NULL,"PLAY MODE", play_options, sizeof (play_options) / sizeof(play_options[0]),0};

MenuEntry highscores_options[] = {{0, ".1 min", NULL, showScores1},
							{1, ".3 min", NULL, showScores2},
							{2, ".5 min", NULL, showScores3},
							{3, ".Back", NULL, NULL}};
							
Menu highscoresMenu = {NULL,"HIGH SCORES", highscores_options, sizeof (highscores_options) / sizeof(highscores_options[0]),0};

int fplay(){startMenu(&playMenu,menu_posH, menu_posV); return 0;}
int fOptions() {startMenu(&optionsMenu,menu_posH, menu_posV); return 0;}
int fHighScores(){ startMenu(&highscoresMenu,menu_posH, menu_posV); return 0;}
int fHelp(){ return 0;}
int fAbout(){ return 0;}

int printLogo()
{
	draw_sprite( create_sprite(bejeweledLogo, LOGO_X,LOGO_Y, video), video);
	return 0;
}

MenuEntry main_options[] = {{0, ".Play!", NULL, fplay},
							{1, ".High Scores", NULL,fHighScores},
							{2, ".Options", NULL, fOptions},
							{3, ".Help", NULL, fHelp},
							{4, ".About", NULL,fAbout},
							{5, ".Quit", NULL, NULL}};
							
Menu mainMenu = {NULL,">> BEJEWELED <<", main_options, sizeof (main_options) / sizeof(main_options[0]),0};

int getKey()
{
	int key;
	int valida = 0;
	
	do
	{
		while(queueEmpty(&keys_queue))
		{}
		key = queueGet(&keys_queue);
		
		switch(key)
		{
			case Q: valida = 1; break;
			case W: valida = 1; break;
			case E: valida = 1; break;
			case R: valida = 1; break;
			case T: valida = 1; break;
			case Y: valida = 1; break;
			case U: valida = 1; break;
			case I: valida = 1; break;
			case O: valida = 1; break;
			case P: valida = 1; break;
			case A: valida = 1; break;
			case S: valida = 1; break;
			case D: valida = 1; break;
			case F: valida = 1; break;
			case G: valida = 1; break;
			case H: valida = 1; break;
			case J: valida = 1; break;
			case K: valida = 1; break;
			case L: valida = 1; break;
			case Z: valida = 1; break;
			case X: valida = 1; break;
			case C: valida = 1; break;
			case V: valida = 1; break;
			case B: valida = 1; break;
			case N: valida = 1; break;
			case M: valida = 1; break;
			case KEY_1: valida = 1; break;
			case KEY_2: valida = 1; break;
			case KEY_3: valida = 1; break;
			case KEY_4: valida = 1; break;
			case KEY_5: valida = 1; break;
			case KEY_6: valida = 1; break;
			case KEY_7: valida = 1; break;
			case KEY_8: valida = 1; break;
			case KEY_9: valida = 1; break;
			case KEY_0: valida = 1; break;
			case SPACE: valida = 1; break;
			case ENTER: valida = 1; break;
			case UP: valida = 1; break;
			case DOWN: valida = 1; break;
			case LEFT: valida = 1; break;
			case RIGHT: valida = 1; break;
			case CTRL: valida = 1; break;
			case ALT: valida = 1; break;
			case LEFT_SHIFT: valida = 1; break;
			case RIGHT_SHIFT: valida = 1; break;
			case TAB: valida = 1; break;
			case RETURN: valida = 1; break;
		}
	}
	while(!valida);
	
	return key;
	
}

void printKey(int key, int x, int y)
{
	switch(key)
	{
		case Q: drawStringAt("Q", x, y, WHITE, BLACK,1, video, table); break;
		case W: drawStringAt("W", x, y, WHITE, BLACK,1, video, table); break;
		case E: drawStringAt("E", x, y, WHITE, BLACK,1, video, table); break;
		case R: drawStringAt("R", x, y, WHITE, BLACK,1, video, table); break;
		case T: drawStringAt("T", x, y, WHITE, BLACK,1, video, table); break;
		case Y: drawStringAt("Y", x, y, WHITE, BLACK,1, video, table); break;
		case U: drawStringAt("U", x, y, WHITE, BLACK,1, video, table); break;
		case I: drawStringAt("I", x, y, WHITE, BLACK,1, video, table); break;
		case O: drawStringAt("O", x, y, WHITE, BLACK,1, video, table); break;
		case P: drawStringAt("P", x, y, WHITE, BLACK,1, video, table); break;
		case A: drawStringAt("A", x, y, WHITE, BLACK,1, video, table); break;
		case S: drawStringAt("S", x, y, WHITE, BLACK,1, video, table); break;
		case D: drawStringAt("D", x, y, WHITE, BLACK,1, video, table); break;
		case F: drawStringAt("F", x, y, WHITE, BLACK,1, video, table); break;
		case G: drawStringAt("G", x, y, WHITE, BLACK,1, video, table); break;
		case H: drawStringAt("H", x, y, WHITE, BLACK,1, video, table); break;
		case J: drawStringAt("J", x, y, WHITE, BLACK,1, video, table); break;
		case K: drawStringAt("K", x, y, WHITE, BLACK,1, video, table); break;
		case L: drawStringAt("L", x, y, WHITE, BLACK,1, video, table); break;
		case Z: drawStringAt("Z", x, y, WHITE, BLACK,1, video, table); break;
		case X: drawStringAt("X", x, y, WHITE, BLACK,1, video, table); break;
		case C: drawStringAt("C", x, y, WHITE, BLACK,1, video, table); break;
		case V: drawStringAt("V", x, y, WHITE, BLACK,1, video, table); break;
		case B: drawStringAt("B", x, y, WHITE, BLACK,1, video, table); break;
		case N: drawStringAt("N", x, y, WHITE, BLACK,1, video, table); break;
		case M: drawStringAt("M", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_1: drawStringAt("1", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_2: drawStringAt("2", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_3: drawStringAt("3", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_4: drawStringAt("4", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_5: drawStringAt("5", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_6: drawStringAt("6", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_7: drawStringAt("7", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_8: drawStringAt("8", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_9: drawStringAt("9", x, y, WHITE, BLACK,1, video, table); break;
		case KEY_0: drawStringAt("0", x, y, WHITE, BLACK,1, video, table); break;
		case SPACE: drawStringAt("SPACE", x, y, WHITE, BLACK,1, video, table); break;
		case ENTER: drawStringAt("ENTER", x, y, WHITE, BLACK,1, video, table); break;
		case UP: drawStringAt("UP", x, y, WHITE, BLACK,1, video, table); break;
		case DOWN: drawStringAt("DOWN", x, y, WHITE, BLACK,1, video, table); break;
		case LEFT: drawStringAt("LEFT", x, y, WHITE, BLACK,1, video, table); break;
		case RIGHT: drawStringAt("RIGHT", x, y, WHITE, BLACK,1, video, table); break;
		case CTRL: drawStringAt("CTRL", x, y, WHITE, BLACK,1, video, table); break;
		case ALT: drawStringAt("ALT", x, y, WHITE, BLACK,1, video, table); break;
		case LEFT_SHIFT: drawStringAt("LEFT SHIFT", x, y, WHITE, BLACK,1, video, table); break;
		case RIGHT_SHIFT: drawStringAt("RIGHT SHIFT", x, y, WHITE, BLACK,1, video, table); break;
		case TAB: drawStringAt("TAB", x, y, WHITE, BLACK,1, video, table); break;
		case RETURN: drawStringAt("RETURN", x, y, WHITE, BLACK,1, video, table); break;
		case NULL: drawStringAt(" ", x, y, BLACK, BLACK,1, video, table); break;
		
	}
}

void updateResolution(int res)
{
	switch(res)
	{
		case MODE_640x480:
				resolution = MODE_640x480;
				axisH = 640;
				axisV = 480;
				break;
		case MODE_800x600:
				resolution = MODE_800x600;
				axisH = 800;
				axisV = 600;
				break;
		case MODE_1024x768:
				resolution = MODE_1024x768;
				axisH = 1024;
				axisV = 768;
				break;
		case MODE_1280x1024:
				resolution = MODE_1280x1024;
				axisH = 1280;
				axisV = 1024;
				break;
	}
}

void showScores(int mode)
{
	clear_screen(BLACK, video);
	
	switch(mode)
	{
		case GAMEMODE1: printScores("MODE 1 MINUTES", highscores1, menu_posH, menu_posV, YELLOW, WHITE, BLACK, video, table); break;
		case GAMEMODE2: printScores("MODE 3 MINUTES", highscores2, menu_posH, menu_posV, YELLOW, WHITE, BLACK, video, table); break;
		case GAMEMODE3: printScores("MODE 5 MINUTES", highscores3, menu_posH, menu_posV, YELLOW, WHITE, BLACK, video, table);	break;
	}
	
	int valida = 0;
	int scancode;
	
	do
	{
		while(queueEmpty(&keys_queue))
		{}
	
		scancode = queueGet(&keys_queue);
		
		if(scancode == ESC)
			valida = 1;
	}
	while(!valida);
}

void initialize()
{
/*	key_up = W;
	key_down = S;
	key_left = A;
	key_right = D;
	key_action = ENTER;
	key_pause = P;

	updateResolution(MODE_800x600);*/
	
	//Inicializa configuracoes: resolucao, teclas, som
	loadConfigurations();
	
	//Carrega HighScores
	loadScores(highscores1, SCORES1_PATH);
	loadScores(highscores2, SCORES2_PATH);
	loadScores(highscores3, SCORES3_PATH);
	
	//Carrega caracteres
	load_char_table(table);
	
	//Entra modo de video
	video = enter_graphics(resolution, &map);
	
	//Inicia teclado
	install_asm_irq_handler(KBD_IRQ, kbd_isr, &old_kbd_irq);
	queueInit(&keys_queue);
}

Note Ary[] = {{Sol4, 238}, {Mi4, 238}, {Sol4, 238}, {Do5, 238}, {Re5, 238}, {Mi5, 238},
			  {Sol5, 238}, {Sol4, 238}, {Do5, 238}, {Re5, 238}, {Mi5, 238}, {Sol5, 238},
			  {Sol5, 238}, {La4, 238}, {Do5, 238}, {Re5, 238}, {Mi5, 238}, {Sol5, 238},
			  {Sol5, 238}, {Si4, 238}, {Re5, 238}, {Mi5, 238}, {Sol5, 238}, {Si4, 238}};		 

Song Intro = { sizeof(Ary)/sizeof(Note), 10, Ary};

void startGame()
{
	clear_screen(BLACK,video);
	drawStringAt("Loading...", NEWSCORE_X, NEWSCORE_Y, NEWSCORE_COLOR, BLACK, NEWSCORE_DIMENSION, video, table);
	drawStringAt("We are robbing a bank. Please wait.", NEWSCORE_MSG2_X, NEWSCORE_MSG2_Y, NEWSCORE_MSG2_COLOR, BLACK,NEWSCORE_MSG2_DIMENSION, video, table);

	
	if(sounds)
		play_song(&Intro);
	else
		sleep(5);
		
	startMenu(&mainMenu, menu_posH, menu_posV);
}

void finalize()
{
	//Finaliza teclado
	reinstall_asm_irq_handler(KBD_IRQ, &old_kbd_irq);
	
	//Sai do modo de video
	leave_graphics(map);
	
	saveConfigurations();
	
	//Guarda HighScores
	saveScores(highscores1,SCORES1_PATH);
	saveScores(highscores2,SCORES2_PATH);
	saveScores(highscores3,SCORES3_PATH);
}

void loadConfigurations()
{
	FILE * fin;

	fin = fopen(CONFIGURATIONS_PATH, "r");

	fscanf(fin,"%d", &resolution);
	fscanf(fin,"%d", &sounds);
	fscanf(fin,"%d", &key_up);
	fscanf(fin,"%d", &key_down);
	fscanf(fin,"%d", &key_left);
	fscanf(fin,"%d", &key_right);
	fscanf(fin,"%d", &key_action);
	fscanf(fin,"%d", &key_pause);
	
	fclose(fin);
	
	updateResolution(resolution);
}

void saveConfigurations()
{
	FILE * fout;
	
	fout = fopen(CONFIGURATIONS_PATH, "w");

	fprintf(fout,"%d\n", resolution);
	fprintf(fout,"%d\n", sounds);
	fprintf(fout,"%d\n", key_up);
	fprintf(fout,"%d\n", key_down );
	fprintf(fout,"%d\n", key_left );
	fprintf(fout,"%d\n", key_right );
	fprintf(fout,"%d\n", key_action );
	fprintf(fout,"%d\n", key_pause );

	fclose(fout);
}
